package com.baoyouqun.service.impl;

import com.baoyouqun.base.utils.FileTypeUtil;
import com.baoyouqun.entity.FileInfoLocal;
import com.baoyouqun.mapper.FileInfoLocalMapper;
import com.baoyouqun.service.FilePreviewService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

/**
 * 文件预览服务实现类
 */
@Service
@Slf4j
public class FilePreviewServiceImpl implements FilePreviewService {

    @Resource
    private FileInfoLocalMapper fileInfoMapper;

    @Value("${file.storage.base-path}")  // 修复路径配置，与存储服务保持一致
    private String rootPath;

    @Value("${file.storage.temp-path}")
    private String tempPath;

    @Override
    public void previewFile(String fileId, HttpServletResponse response) throws IOException {
        // 修复ID类型转换
        Long id;
        try {
            id = Long.parseLong(fileId);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("文件ID格式错误");
        }

        // 获取文件信息
        FileInfoLocal fileInfo = fileInfoMapper.selectById(id);
        Assert.notNull(fileInfo, "文件不存在或已被删除");

        String contentType = fileInfo.getFileType();
        String previewType = FileTypeUtil.getPreviewType(contentType);
        Path fullPath = Paths.get(rootPath, fileInfo.getRelativePath(), fileInfo.getStorageFileName());

        // 根据文件类型处理预览
        switch (previewType) {
            case "image":
                previewImage(fullPath, contentType, response);
                break;
            case "text":
                previewText(fullPath, response);
                break;
            case "pdf":
                previewPdf(fullPath, response);
                break;
            case "office":
                previewOfficeFile(fullPath, contentType, fileInfo, response);
                break;
            default:
                throw new UnsupportedOperationException("不支持的文件预览类型: " + contentType);
        }
    }

    /**
     * 预览图片
     */
    private void previewImage(Path fullPath, String contentType, HttpServletResponse response) throws IOException {
        response.setContentType(contentType);
        try (InputStream is = Files.newInputStream(fullPath);
             OutputStream os = response.getOutputStream()) {
            byte[] buffer = new byte[8192];  // 增大缓冲区
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        }
    }

    /**
     * 预览文本文件
     */
    private void previewText(Path fullPath, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (BufferedReader br = Files.newBufferedReader(fullPath, StandardCharsets.UTF_8);
             PrintWriter out = response.getWriter()) {

            out.println("<html><body><pre>");
            String line;
            while ((line = br.readLine()) != null) {
                out.println(escapeHtml(line));
            }
            out.println("</pre></body></html>");
        }
    }

    /**
     * 预览PDF文件
     */
    private void previewPdf(Path fullPath, HttpServletResponse response) throws IOException {
        response.setContentType("application/pdf");
        try (InputStream is = Files.newInputStream(fullPath);
             OutputStream os = response.getOutputStream()) {
            byte[] buffer = new byte[8192];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        }
    }

    /**
     * 预览Office文件（转换为PDF后预览）
     */
    private void previewOfficeFile(Path fullPath, String contentType, FileInfoLocal fileInfo, HttpServletResponse response) throws IOException {
        // 创建临时目录
        Path tempDir = Paths.get(tempPath);
        if (!Files.exists(tempDir)) {
            Files.createDirectories(tempDir);
        }

        // 生成临时PDF文件路径
        String pdfFileName = fileInfo.getStorageFileName() + ".pdf";
        Path pdfFilePath = tempDir.resolve(pdfFileName);

        try {
            // 转换为PDF
            if (contentType.contains("word")) {
                convertWordToPdf(fullPath, pdfFilePath);
            } else if (contentType.contains("excel")) {
                throw new UnsupportedOperationException("Excel预览暂未实现");
            } else if (contentType.contains("powerpoint")) {
                throw new UnsupportedOperationException("PPT预览暂未实现");
            }

            // 预览转换后的PDF
            previewPdf(pdfFilePath, response);
        } finally {
            // 延迟删除临时文件（确保预览完成）
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(30);  // 30秒后删除
                    Files.deleteIfExists(pdfFilePath);
                } catch (Exception e) {
                    log.error("删除临时PDF文件失败", e);
                }
            }).start();
        }
    }

    /**
     * 将Word文档转换为PDF（使用docx4j实现）
     */
    private void convertWordToPdf(Path wordPath, Path pdfPath) throws IOException {
        try (InputStream is = Files.newInputStream(wordPath);
             OutputStream os = Files.newOutputStream(pdfPath)) {
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
            Docx4J.toPDF(mlPackage, os);
        } catch (Exception e) {
            throw new IOException("Word转PDF失败", e);
        }
    }

    /**
     * 生成图片缩略图
     */
    @Override
    public void generateThumbnail(FileInfoLocal fileInfo, int width, int height, HttpServletResponse response) throws IOException {
        Assert.isTrue(FileTypeUtil.isImage(fileInfo.getFileType()), "只有图片文件可以生成缩略图");

        Path fullPath = Paths.get(rootPath, fileInfo.getRelativePath(), fileInfo.getStorageFileName());
        response.setContentType(fileInfo.getFileType());

        try (OutputStream os = response.getOutputStream()) {
            // 使用Thumbnails生成缩略图（需引入thumbnailator依赖）
            Thumbnails.of(fullPath.toFile())
                    .size(width, height)
                    .keepAspectRatio(true)
                    .outputFormat(getImageFormat(fileInfo.getFileType()))
                    .toOutputStream(os);
        }
    }

    /**
     * 获取图片格式
     */
    private String getImageFormat(String contentType) {
        if ("image/jpeg".equals(contentType) || "image/pjpeg".equals(contentType)) {
            return "jpg";
        } else if ("image/png".equals(contentType)) {
            return "png";
        } else if ("image/gif".equals(contentType)) {
            return "gif";
        } else if ("image/bmp".equals(contentType)) {
            return "bmp";
        }
        return "jpg";
    }

    /**
     * 转义HTML特殊字符
     */
    private String escapeHtml(String input) {
        if (input == null) {
            return "";
        }
        return input.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&#39;");
    }
}